package com.study.modules.saas.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.study.common.constants.RedisCache;
import com.study.common.BusinessException;
import com.study.modules.saas.repository.dao.RoleDao;
import com.study.modules.saas.repository.model.MenuDO;
import com.study.modules.saas.repository.model.RoleDO;
import com.study.modules.saas.repository.model.RoleMenuDO;
import com.study.security.domain.CurrentUser;
import com.study.security.utils.SecurityUtils;
import com.study.vo.RoleRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RoleService {

    @Autowired
    MenuService menuService;

    @Autowired
    RoleDao roleDao;

    @Autowired
    RedisCache redisCache;

    @Autowired
    RoleMenuService roleMenuService;

    @Autowired
    UserRoleService userRoleService;

    /**
     * 根据roleId查找角色
     *
     * @param roleId
     * @return
     */
    public RoleDO getRoleById(Integer roleId) {

        RoleDO roleDO = roleDao.selectById(roleId);
        if (ObjectUtils.isNull(roleDO)) {
            throw new BusinessException("没有找到角色id:【" + roleId + "】");
        }
        List<Integer> menuIds = menuService.getRoleMenuIds(roleId);
        if (menuIds == null || menuIds.isEmpty()) {
            throw new BusinessException("该角色没有所属菜单");
        }
        roleDO.setMenuIds(menuIds);
        return roleDO;
    }

    /**
     * 获取角色
     *
     * @param roleId
     * @return
     */
    public RoleDO getRoleByRoleId(Integer roleId) {
        RoleDO roleDO = this.getRoleById(roleId);

        List<String> jsonStr = redisCache.getMenus(roleDO.getMenuIds());

        List<MenuDO> menus = null;
        if (!jsonStr.isEmpty()) {
            menus = jsonStr.stream().map(menusJSON -> JSONObject.parseObject(menusJSON, MenuDO.class)).collect(Collectors.toList());
        }

        if (menus == null || menus.isEmpty()) {
            menus = menuService.getMenuList(roleDO.getMenuIds());
        }

        log.info("【menus】:{}", menus);

        roleDO.setMenuList(menus);
        return roleDO;
    }

    /**
     * 根据uuid 查找role
     *
     * @param uuid
     * @return
     */
    public RoleDO getRoleByUuid(String uuid) {
        return roleDao.selectRoleByUuid(uuid);
    }

    /**
     * 创建角色
     *
     * @param request
     */
    @Transactional(rollbackFor = BusinessException.class)
    public void createRole(RoleRequest request) {

        Integer roleByName = this.getRoleByName(request.getName());
        if (roleByName != null && roleByName > 0) {
            throw new BusinessException("角色名称重复");
        }

        CurrentUser currentUser = SecurityUtils.getCurrentUser();

        RoleDO roleDO = new RoleDO();
        roleDO.setRoleName(request.getName());
        roleDO.setStatus(request.getStatus());
        roleDO.setRemark(request.getRemark());
        roleDO.setCreatedBy(currentUser.getUuid());
        roleDO.setCreatedAt(new Date());

        boolean success = roleDao.insert(roleDO) > 0;
        if (!success) {
            throw new BusinessException("添加角色失败");
        }

        log.info("角色id:{}", roleDO.getId());

        String menuIds = request.getMenuIds();
        String[] split = menuIds.split(",");
        for (String s : split) {
            MenuDO menuDO = menuService.getMenuById(Integer.valueOf(s));
            if (ObjectUtils.isNull(menuDO)) {
                throw new BusinessException("选择的菜单有异常");
            }
            log.info("----- 角色id:{}", roleDO.getId());
            RoleMenuDO roleMenuDO = new RoleMenuDO();
            roleMenuDO.setRoleId(roleDO.getId());
            roleMenuDO.setMenuId(Integer.valueOf(s));
            boolean re = roleMenuService.addRoleMenu(roleMenuDO) > 0;
            // TODO 缓存?
            if (!re) {
                throw new BusinessException("关联数据添加失败");
            }
        }
    }

    /**
     * 角色名称查询角色
     *
     * @param roleName
     * @return
     */
    public Integer getRoleByName(String roleName) {
        return roleDao.selectCount(new LambdaQueryWrapper<RoleDO>()
                .eq(RoleDO::getRoleName, roleName)
                .isNull(RoleDO::getDeletedAt));
    }


    /**
     * roleId 获得RoleDO
     *
     * @param id
     * @return
     */
    public RoleDO getRoleDOByRoleId(Integer id) {
        return roleDao.selectOne(new LambdaQueryWrapper<RoleDO>()
                .eq(RoleDO::getId, id)
                .isNull(RoleDO::getDeletedAt));
    }

    /**
     * 删除角色
     *
     * @param roleId
     * @return
     */
    @Transactional(rollbackFor = BusinessException.class)
    public void deleteRole(Integer roleId) {
        RoleDO roleDO = this.getRoleDOByRoleId(roleId);

        if (ObjectUtils.isNull(roleDO)) {
            log.info("【删除角色id:{} 不存在】", roleId);
            throw new BusinessException("当前角色不存在");
        }
        String uuid = SecurityUtils.getCurrentUser().getUuid();

        roleDO.setDeletedAt(new Date());
        roleDO.setDeletedBy(uuid);
        boolean success = roleDao.updateById(roleDO) > 0;
        if (!success) {
            throw new BusinessException("删除角色失败");
        }
        Integer count = userRoleService.getUserRoleByRoleIdCount(roleId);

        if(count != null && count > 0){
            boolean delete = userRoleService.deleteUserRoleByRoleId(roleId) > 0;
            if(!delete){
                log.info("删除角色id{}和用户关联失败",roleId);
                throw new BusinessException("删除角色失败");
            }
        }
        // todo 清空缓存
    }

}
